from datetime import datetime
from typing import List

from sqlalchemy import Integer, String, Boolean, Float, DateTime, ForeignKey, Table, Column, ForeignKeyConstraint, func
from sqlalchemy.orm import Mapped, mapped_column, relationship

from util.DataBaseTools import Base


class SysDictModel(Base):
    __tablename__ = 'sys_dict'

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    sys_dict_id: Mapped[int] = mapped_column(Integer)
    sys_dict_name: Mapped[str] = mapped_column(String(50))

    sys_dict_details: Mapped[List['SysDictDetailModel']] = relationship('SysDictDetailModel', lazy=None, primaryjoin='SysDictModel.sys_dict_id==SysDictDetailModel.sys_dict_id', order_by='asc(SysDictDetailModel.sys_dict_item_id)')

    def __repr__(self):
        return f'id: {self.id}, sys_dict_id: {self.sys_dict_id}, sys_dict_name: {self.sys_dict_name}, sys_dict_details: {self.sys_dict_details}'


class SysDictDetailModel(Base):
    __tablename__ = 'sys_dict_detail'

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    sys_dict_id: Mapped[int] = mapped_column(Integer, ForeignKey('sys_dict.sys_dict_id'))
    sys_dict_item_id: Mapped[int] = mapped_column(Integer)
    sys_dict_item_name: Mapped[str] = mapped_column(String(50))

    def __repr__(self):
        return f'id: {self.id}, sys_dict_id: {self.sys_dict_id}, sys_dict_item_id: {self.sys_dict_item_id}, sys_dict_item_name: {self.sys_dict_item_name}'


class UserModel(Base):
    __tablename__ = 'user'

    user_id: Mapped[str] = mapped_column(String(20), primary_key=True)
    port_id: Mapped[int] = mapped_column(Integer)
    user_name: Mapped[str] = mapped_column(String(50))
    password: Mapped[str] = mapped_column(String(255))
    status: Mapped[int] = mapped_column(Integer)
    create_date: Mapped[datetime] = mapped_column(DateTime, default=func.now())

    def __repr__(self):
        return f'user_id: {self.user_id}, port_id: {self.port_id}, user_name: {self.user_name}, status: {self.status}'


class MenuModel(Base):
    __tablename__ = 'menu'

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    parent_id: Mapped[int] = mapped_column(Integer)
    menu_id: Mapped[int] = mapped_column(Integer)
    menu_name: Mapped[str] = mapped_column(String(50))
    function_path: Mapped[str] = mapped_column(String(255))
    function_name: Mapped[str] = mapped_column(String(50))
    level: Mapped[int] = mapped_column(Integer)

    port_menu: Mapped['PortMenuModel'] = relationship('PortMenuModel', lazy=None,
                                                      primaryjoin="and_(PortMenuModel.menu_id == MenuModel.menu_id, PortMenuModel.function_path == MenuModel.function_path)",
                                                      order_by='asc(MenuModel.menu_id), asc(MenuModel.level)')

    def __repr__(self):
        return f'parent_id: {self.parent_id}, menu_id: {self.menu_id}, menu_name: {self.menu_name}, function_path: {self.function_path}, function_name: {self.function_name}, level: {self.level}, port_menu: {self.port_menu}'


class PortMenuModel(Base):
    __tablename__ = 'port_menu'

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    port_id: Mapped[int] = mapped_column(Integer)
    menu_id: Mapped[int] = mapped_column(Integer)
    function_path: Mapped[str] = mapped_column(String(255))
    flag: Mapped[int] = mapped_column(Integer)

    __table_args__ = (
        ForeignKeyConstraint(
            [menu_id, function_path],
            [MenuModel.menu_id, MenuModel.function_path]
        ),
    )

    def __repr__(self):
        return f'port_id: {self.port_id}, menu_id: {self.menu_id}, function_path: {self.function_path}, flag: {self.flag}'
